import baostock as bs
import urllib.request
from dao.db_connect import db_connect as db

"""
code	证券代码	
pubDate	公司发布财报的日期	
statDate	财报统计的季度的最后一天, 比如2017-03-31, 2017-06-30	
roeAvg	净资产收益率(平均)(%)	归属母公司股东净利润/[(期初归属母公司股东的权益+期末归属母公司股东的权益)/2]*100%
npMargin	销售净利率(%)	净利润/营业收入*100%
gpMargin	销售毛利率(%)	毛利/营业收入*100%=(营业收入-营业成本)/营业收入*100%
netProfit	净利润(元)	
epsTTM	每股收益	归属母公司股东的净利润TTM/最新总股本
MBRevenue	主营营业收入(元)	
totalShare	总股本	
liqaShare	流通股本
"""
profit = ['code', 'pubDate', 'statDate', 'roeAvg', 'npMargin', 'gpMargin',
          'netProfit', 'epsTTM', 'MBRevenue', 'totalShare', 'liqaShare']
"""
code	证券代码	
pubDate	公司发布财报的日期	
statDate	财报统计的季度的最后一天, 比如2017-03-31, 2017-06-30	
YOYEquity	净资产同比增长率	(本期净资产-上年同期净资产)/上年同期净资产的绝对值*100%
YOYAsset	总资产同比增长率	(本期总资产-上年同期总资产)/上年同期总资产的绝对值*100%
YOYNI	净利润同比增长率	(本期净利润-上年同期净利润)/上年同期净利润的绝对值*100%
YOYEPSBasic	基本每股收益同比增长率	(本期基本每股收益-上年同期基本每股收益)/上年同期基本每股收益的绝对值*100%
YOYPNI	归属母公司股东净利润同比增长率	(本期归属母公司股东净利润-上年同期归属母公司股东净利润)/上年同期归属母公司股东净利润的绝对值*100%
"""
growth = ['code', 'pubDate', 'statDate', 'YOYEquity', 'YOYAsset', 'YOYNI',
          'YOYEPSBasic', 'YOYPNI']
"""
code	证券代码	
pubDate	公司发布财报的日期	
statDate	财报统计的季度的最后一天, 比如2017-03-31, 2017-06-30	
currentRatio	流动比率	流动资产/流动负债
quickRatio	速动比率	(流动资产-存货净额)/流动负债
cashRatio	现金比率	(货币资金+交易性金融资产)/流动负债
YOYLiability	总负债同比增长率	(本期总负债-上年同期总负债)/上年同期中负债的绝对值*100%
liabilityToAsset	资产负债率	负债总额/资产总额
assetToEquity	权益乘数	资产总额/股东权益总额=1/(1-资产负债率)
"""
balance = ['code', 'pubDate', 'statDate', 'currentRatio', 'quickRatio',
           'cashRatio', 'YOYLiability', 'liabilityToAsset', 'assetToEquity']
"""
code	证券代码	
pubDate	公司发布财报的日期	
statDate	财报统计的季度的最后一天, 比如2017-03-31, 2017-06-30	
CAToAsset	流动资产除以总资产	
NCAToAsset	非流动资产除以总资产	
tangibleAssetToAsset	有形资产除以总资产	
ebitToInterest	已获利息倍数	息税前利润/利息费用
CFOToOR	经营活动产生的现金流量净额除以营业收入	
CFOToNP	经营性现金净流量除以净利润	
CFOToGr	经营性现金净流量除以营业总收入	
"""
cash_flow = ['code', 'pubDate', 'statDate', 'CAToAsset', 'NCAToAsset',
             'tangibleAssetToAsset', 'ebitToInterest', 'CFOToOR', 'CFOToNP',
             'CFOToGr']
"""
### 获取沪深A股估值指标(日频)数据 ####
peTTM    滚动市盈率
psTTM    滚动市销率
pcfNcfTTM    滚动市现率
pbMRQ    市净率
"""
daily = ['close', 'peTTM', 'pbMRQ', 'psTTM', 'pcfNcfTTM']

share_query_names = ["profit", "growth", "cash_flow"]
share_query_label = {
    "profit": profit,
    "growth": growth,
    "cash_flow": cash_flow
}
share_query_func = {
    "profit": bs.query_profit_data,
    "growth": bs.query_growth_data,
    "cash_flow": bs.query_cash_flow_data
}

sina_shares = {
    'name': 0,
    'opening_price': 1,
    'closing_price': 2,
    'current_price': 3,
    'max_price': 4,
    'min_price': 5,
    'trading': 8,
    'business': 9,
    'date': 30,
    'time': 31,
}

identification_error = 100  # 财报数据未生成
data_missing = 101  # 数据库内无相关数据
success = 200  # 请求成功


def remake_components(components):
    share_data = {}
    for component in components:
        # 处理综合评价数据
        if component["ori_index"] == 2:
            diagnosis = component["data"]["datas"][0]
            new_diagnosis = {
                "ko": diagnosis.get("ko"),
                "rank": diagnosis.get("牛叉诊股综合评分行业排名"),
                "bull": diagnosis.get("bull"),
                "score": diagnosis.get("牛叉诊股综合评分"),
                "short": diagnosis.get("牛叉诊股_短期趋势"),
                "mid": diagnosis.get("牛叉诊股_中期趋势"),
                "long": diagnosis.get("牛叉诊股_长期趋势"),
                "cateData": diagnosis.get("cateData")
            }
            share_data["diagnosisList"] = new_diagnosis
        if component["ori_index"] == 15:
            radar = component["data"]["datas"]
            # 注意不要修改名字的顺序，此处与前端显示相关
            name_list = ["盈利能力", "成长能力", "营运能力", "偿债能力", "现金流"]
            radar_values = []
            radar_names = []
            for radar_data in radar:
                radar_names.append(radar_data["时间"])
                radar_value = {"name": radar_data["时间"]}
                values = []
                for name in name_list:
                    value = radar_data.get(name)
                    values.append(value)
                radar_value["value"] = values
                radar_values.append(radar_value)
            new_radar = dict(names=radar_names, data=radar_values)
            share_data["radar"] = new_radar
        if component["ori_index"] == 16:
            content = str(component["data"]["content"])
            content = content[content.find('\">') + 2: content.rfind('</span>')]
            share_data["content"] = content
    return share_data


# time_list: [(2018,2), ...]
# return: code, msg, data
def finance_generate(time_list, share_code):
    code = success
    msg = "数据获取成功！"
    login = bs.login()
    if login.error_code != '0':
        msg = "接口失效"
        code = data_missing
        bs.logout()
        return code, msg, None

    finance_data = []
    for finance_time in time_list:
        query_dic = {}
        for query_name in share_query_names:
            query_rs = share_query_func[query_name](code=share_code, year=finance_time[0], quarter=finance_time[1])
            if query_rs.error_code != '0':
                msg = "财报获取异常"
                code = data_missing
                bs.logout()
                return code, msg, None
            if len(query_rs.data) == 0:
                msg = "当前查询的财报不存在"
                code = identification_error
                bs.logout()
                return code, msg, None
            query_data = query_rs.get_row_data()
            query_label = share_query_label[query_name]
            for index in range(len(query_label)):
                query_dic[query_label[index]] = query_data[index]

        query_rs_dic = {"pubDate": query_dic.get("statDate")}
        query_result_labels = [
            "netProfit",  # 净利润(元)
            "MBRevenue",  # 营业收入(元)
            "YOYNI",  # 净利润(同比增长率)(%)
            "epsTTM",  # 基本每股收益(元)
            "roeAvg",  # 净资产收益率roe(%)
            "bpsAvg",  # 每股净资产bps(元)
            "epsCFO",  # 每股现金流量净额(元)
            "gpMargin",  # 销售毛利率(%)
        ]

        CFOToNP = None if len(query_dic["CFOToNP"]) == 0 else float(query_dic["CFOToNP"])
        for result_label in query_result_labels:
            result_data = query_dic.get(result_label)
            if result_data is None or len(result_data) == 0:
                result_data = None
            else:
                result_data = float(result_data)
            if result_data == 'bpsAvg':
                if query_rs_dic['roeAvg'] is None or query_rs_dic['epsTTM'] is None:
                    result_data = None
                else:
                    result_data = query_rs_dic['epsTTM'] / query_rs_dic['roeAvg']
            if result_data == 'epsCFO':
                if query_rs_dic['epsTTM'] is None or CFOToNP is None:
                    result_data = None
                else:
                    result_data = query_rs_dic['epsTTM'] * CFOToNP
            query_rs_dic[result_label] = result_data

        finance_data.append(query_rs_dic)
    bs.logout()
    return code, msg, finance_data


def common_generate(finance_time, share_label, share_id):
    code = success
    msg = "数据获取成功！"
    login = bs.login()
    if login.error_code != '0':
        msg = "接口失效"
        code = data_missing
        bs.logout()
        return code, msg, None

    query_dic = {}
    query_rs = bs.query_profit_data(code=f"{share_label}.{share_id}", year=finance_time[0], quarter=finance_time[1])
    if query_rs.error_code != '0':
        msg = "数据获取异常"
        code = data_missing
        bs.logout()
        return code, msg, None
    if len(query_rs.data) == 0:
        msg = "当前查询的数据不存在"
        code = identification_error
        bs.logout()
        return code, msg, None
    query_data = query_rs.get_row_data()
    for index in range(len(profit)):
        query_dic[profit[index]] = query_data[index]

    query_rs_dic = {
        "totalShare": float(query_dic["totalShare"]),
        "liqaShare": float(query_dic["liqaShare"]),
    }

    query_rs = bs.query_history_k_data_plus(
        f"{share_label}.{share_id}", "close,peTTM,pbMRQ,psTTM,pcfNcfTTM",
        start_date=finance_time[2], end_date=finance_time[2], frequency="d", adjustflag="3"
    )
    if query_rs.error_code != '0':
        msg = "数据获取异常"
        code = data_missing
        bs.logout()
        return code, msg, None
    if len(query_rs.data) == 0:
        msg = "当前查询的数据不存在"
        code = identification_error
        bs.logout()
        return code, msg, None

    result_list = query_rs.get_row_data()
    for index in range(len(daily)):
        query_rs_dic[daily[index]] = float(result_list[index])

    totalMarket = float(query_rs_dic["totalShare"]) * float(query_rs_dic["close"])
    liqaMarket = float(query_rs_dic["liqaShare"]) * float(query_rs_dic["close"])

    query_rs_dic["totalMarket"] = totalMarket
    query_rs_dic["liqaMarket"] = liqaMarket

    bs.logout()
    return code, msg, query_rs_dic


def update_shares_cache(shares):
    share_url = f'http://hq.sinajs.cn/list='
    share_id_list = []
    share_text = ""
    share_count = 0
    # print(shares)
    for share in shares:
        # print(share)
        share_label = str(share['share_label']).lower()
        share_id = share['share_id']
        share_id_list.append(share_id)
        share_url += f'{share_label}{share_id},'
        share_count = share_count + 1
        if share_count >= 200:
            share_response = urllib.request.urlopen(share_url)
            share_text += str(share_response.read().decode("gbk"))
            share_count = 0
            share_url = f'http://hq.sinajs.cn/list='

    if share_count != 0:
        share_response = urllib.request.urlopen(share_url)
        share_text += str(share_response.read().decode("gbk"))

    query_sql = f'select id, label, name, summary from carbon_shares ' \
                f'where id in {tuple(share_id_list)} order by id'
    data = db.queryAll(query_sql)
    if not data:
        return None
    for share_data in data:
        share_string = share_text[0: share_text.find('var', 3)]
        share_text = share_text[share_text.find('var', 3):]

        share_string = share_string[share_string.find('"') + 1: -3]
        share_list = share_string.split(',')

        share_data['current_price'] = share_list[sina_shares['current_price']]
        current_price = float(share_list[sina_shares['current_price']])
        closing_price = float(share_list[sina_shares['closing_price']])

        share_data['price_range'] = str(round((current_price - closing_price) / closing_price, 4))
        share_data['isExpanded'] = 0

    data.sort(key=lambda x: x['price_range'], reverse=True)
    return data
